﻿package de.gameduell.framework.application.controller {
	import de.gameduell.framework.util.FlashVars;
	import de.gameduell.framework.application.protocol.LocalProtocol;
	import de.gameduell.framework.application.protocol.SingleplayerProtocol;
	import de.gameduell.framework.command.History;
	import de.gameduell.framework.debug.Debug;
	import de.gameduell.framework.game.GameSet.ISet;
	import de.gameduell.framework.game.GameSet.SetEvent;
	import de.gameduell.framework.security.SecureNumber;
	import de.gameduell.framework.test.TestMode;
	import de.gameduell.net.src.communication.ICommunication;
	import de.gameduell.net.src.communication.ServerMessageEvent;

	import flash.events.Event;
	import flash.events.TimerEvent;
	import flash.utils.Timer;

	public class SingleplayerController extends Controller implements ISingleplayerController {

		private static const NO_HISTORY_CREATED:String = "no_history_created;";
		protected var gameSet:ISet;
		protected var intermediateResultTimer:Timer;
		protected var intermediateResultTimerDelay:uint=30000;
		protected var _score:SecureNumber = new SecureNumber(0);
		
		override public function setCommunication(aCommunication:ICommunication):void{
			super.setCommunication(aCommunication);
			communication.addEventListener(SingleplayerProtocol.SET, receiveSet);
			communication.addEventListener(SingleplayerProtocol.LEAVE, receiveLeave);
		}
		
		protected function receiveLeave(event:ServerMessageEvent):void {
			communication.terminate();
		}

		protected function receiveSet(event:ServerMessageEvent):void{
			gameSet.createSetFromEncodedString(event.parameters[0]);
		}	
		
		public function setGameSet(aSet:ISet):void{
			gameSet = aSet;
			gameSet.addEventListener(SetEvent.BUILDED, setBuilded);
			gameSet.addEventListener(SetEvent.BUILDED, checkForTestMode);
		}
		
		protected function setBuilded(event:SetEvent):void {
	
		}
		
		/**
		 * called at the very end of the game,
		 * redirects user to the results page
		 */
		override public function exit(event:Event = null):void {
			try{
				communication.localSend(LocalProtocol.SCORE, String(_score.getValue()));
			}catch(e:Error){
				Debug.trace("SinglePlayerController::exit: local send not available ...", Debug.WARNING);
			}
			FlashVars.setKeyValue("gameScore", String(_score.getValue()));
			super.exit();
		}

		protected function sendStart() : void {
			communication.send(SingleplayerProtocol.START, []);
			
			intermediateResultTimer = new Timer(intermediateResultTimerDelay);
			if(communication.version != "Standalone"){
				intermediateResultTimer.addEventListener(TimerEvent.TIMER, sendIntermediateResult);
				intermediateResultTimer.start();
			}
		}
		
		private function checkForTestMode(event:Event):void {
			gameSet.removeEventListener(SetEvent.BUILDED, checkForTestMode);
			var testmode:TestMode = TestMode.getInstance();
			if(testmode.enabled){
				Debug.trace("SinglePlayerController::checkForTestMode() TESTMODE ACTIVE!", Debug.DEFAULT);
				Debug.trace("SinglePlayerController::calling startGame()", Debug.DEFAULT);				
				sendStart(); // initiate game session
				
				intermediateResultTimer.stop();
				communication.removeEventListener(SingleplayerProtocol.LEAVE, receiveLeave);
				communication.addEventListener(SingleplayerProtocol.LEAVE, leaveTestMode);
				
				var testModeDelay:Timer = new Timer(2000, 1);
				testModeDelay.addEventListener(TimerEvent.TIMER, testModeAction);
				testModeDelay.start();
			}
		}
		
		private function leaveTestMode(event:Event):void {
			communication.terminate();
			var leaveTestModeDelay:Timer = new Timer(2000, 1);
			leaveTestModeDelay.addEventListener(TimerEvent.TIMER, exit);
			leaveTestModeDelay.start();
		}
		
		private function testModeAction(event:TimerEvent):void {
			var testScore:int = TestMode.getInstance().scoreAsInt;
			Debug.trace("SinglePlayerController::testModeAction -> sending score: " + testScore, Debug.DEFAULT);
			sendScore(testScore);
			sendHistory(NO_HISTORY_CREATED);
			Debug.trace("SinglePlayerController::testModeAction -> calling sendEnd()", Debug.DEFAULT);		
			sendEnd();
			Debug.trace("SinglePlayerController::testModeAction TESTMODE DONE ...", Debug.DEFAULT);		
		}

		/**
		 * called when the user finished the game by pressing the close button
		 * sends the results and an abort to the server
		 */
		public function abortGame():void {
			intermediateResultTimer.stop();
			sendIntermediateResult();
			sendCheater();
			sendAbort();
		}

		/**
		 * called when the user finished the game by timeOut, loosing or succeding
		 * sends the results and an end to the server 
		 */
		public function endGame():void {
			intermediateResultTimer.stop();
			sendIntermediateResult();
			sendEnd();
		}
		
		protected function sendIntermediateResult(event:Event=null):void {
			sendScore(_score.getValue());
			var history:String = History.getInstance().toString();
			if (history!=""){
				sendHistory(history);
			}
			else {
				sendHistory(NO_HISTORY_CREATED);
			}
		} 

		protected function sendEnd():void {
			sendCheater();
			communication.send(SingleplayerProtocol.END, []);
		}

		protected function sendScore(score:int):void {
			communication.send(SingleplayerProtocol.SCORE, [score]);
		}

		protected function sendCheater():void {
			communication.send(SingleplayerProtocol.CHEATER, [0, _cheatDetection.getClickPrecision()]);
		}

		protected function sendHistory(history:String):void {
			communication.send(SingleplayerProtocol.HISTORY, [history]);
			History.getInstance().clear();
		}
	}
}
